package com.javacoo.swing.core.data;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.javacoo.swing.api.cache.CacheService;
import com.javacoo.swing.api.http.HttpHandler;
import com.javacoo.swing.api.http.RemoteSetting;
import com.javacoo.swing.api.persistence.PersistService;
import com.javacoo.swing.core.constant.Constant;
import com.javacoo.swing.core.event.DataEvent;
import com.javacoo.swing.core.event.DataType;
import com.javacoo.swing.core.event.MonitorEventBus;
import com.javacoo.swing.core.utils.AmountUtil;
import com.javacoo.swing.core.utils.IPUtils;
import com.javacoo.swing.core.utils.SignUtil;
import com.javacoo.xkernel.spi.ExtensionLoader;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.util.List;
import java.util.Optional;

/**
 * 默认数据处理器
 * <p>说明:</p>
 * <li>支护宝实现</li>
 *
 * @Author DuanYong
 * @Since 2019/8/30 23:47
 * @Version 1.0
 */
@Slf4j
public class AliPayDataHandler extends AbstractDataHandler<JSONArray>{
    /** 需要监控的请求URL */
    private static final String MONITOR_URL_KEY="fundAccountDetail.json";
    /** 结果处理->结果 key*/
    private static final String RESULT_KEY = "result";
    /** 结果处理->详细 key*/
    private static final String RESULT_DETAIL_KEY = "detail";
    /** 结果处理->交易时间 key*/
    private static final String RESULT_TRADE_TILE_KEY = "tradeTime";
    /** 结果处理->支付订单号 key*/
    private static final String RESULT_TRADE_NO_KEY = "tradeNo";
    /** 结果处理->商户订单号 key*/
    private static final String RESULT_ORDER_NO_KEY = "orderNo";
    /** 结果处理->支付金额 key*/
    private static final String RESULT_TRADE_AMOUNT_KEY = "tradeAmount";
    /** 结果处理->账户EMAIL key*/
    private static final String RESULT_ACCOUNT_EMAIL_KEY = "otherAccountEmail";
    /** 结果处理->账户全称 key*/
    private static final String RESULT_ACCOUNT_FULL_NAME_KEY = "otherAccountFullname";
    /** 结果处理->交易备注 key*/
    private static final String RESULT_TRANS_MEMO_KEY = "transMemo";
    /** 结果处理->账户类型 key*/
    private static final String RESULT_ACCOUNT_TYPE_KEY = "accountType";
    /** 结果处理->账户余额 key*/
    private static final String RESULT_BALANCE_KEY = "balance";
    /**远程服务*/
    private HttpHandler httpHandler;
    /**持久服务*/
    private PersistService persistService;
    /**缓存服务*/
    private CacheService cacheService;

    public AliPayDataHandler() {
        this.httpHandler = ExtensionLoader.getExtensionLoader(HttpHandler.class).getDefaultExtension().init(new RemoteSetting());
        this.persistService = ExtensionLoader.getExtensionLoader(PersistService.class).getDefaultExtension();
        this.cacheService = ExtensionLoader.getExtensionLoader(CacheService.class).getDefaultExtension();
        initCache();
    }

    /**
     * 准备数据
     * <p>说明:</p>
     * <li></li>
     *
     * @param data
     * @author duanyong@jccfc.com
     * @date 2020/9/5 22:54
     * @Params data 原始数据
     */
    @Override
    protected Optional<String> readyData(String data) {
        return Optional.ofNullable(data);
    }

    @Override
    protected void doHandle(JSONArray details) {
        for(Object detail : details){
            JSONObject jsonObject = (JSONObject)detail;
            String tradeNo = jsonObject.getString(RESULT_TRADE_NO_KEY);
            String cacheData = cacheService.getCache(Constant.DATA_KEY);
            if(StringUtils.isNotBlank(cacheData) && cacheData.contains(tradeNo)){
                continue;
            }
            MonitorEventBus.getInstance().post(new DataEvent(DataType.LOG_DATA,detail.toString()));
            //execute(jsonObject);
            afterHandle(jsonObject);
        }
    }

    @Override
    protected JSONArray parser(String rawData) {
        JSONObject data = JSON.parseObject(rawData);
        JSONObject result = data.getJSONObject(RESULT_KEY);
        return result.getJSONArray(RESULT_DETAIL_KEY);
    }
    /**
     *  缓存初始化
     * <p>说明:</p>
     * <li></li>
     * @author DuanYong
     * @since 2019/8/30 13:44
     * @version 1.0
     */
    private void initCache(){
        Optional<List<JSONObject>> dataListOptional = persistService.getList(new JSONObject());
        dataListOptional.ifPresent(dataList-> dataList.stream().forEach(jsonObject -> jsonObject.forEach((key, value) -> cacheService.putCache(key, String.valueOf(value)))));
    }
    /**
     * 执行处理
     * <p>说明:</p>
     * <li></li>
     * @Author DuanYong
     * @Since 2019/8/31 0:24
     * @Version 1.0
     * @Params jsonObject
     */
    private void execute(final JSONObject jsonObject){
        JSONObject result = pushPayOrder(jsonObject);
        if(null == result.get(Constant.REMOTE_RETURN_KEY) || !Constant.REMOTE_RETURN_VALUE_SUCCESS.equals(result.get(Constant.REMOTE_RETURN_KEY))){
            MonitorEventBus.getInstance().post(new DataEvent(DataType.LOG_DATA,"推送数据失败:"+result.toString()));
            return;
        }
        MonitorEventBus.getInstance().post(new DataEvent(DataType.LOG_DATA,"推送数据成功:"+result.toString()));
        afterHandle(jsonObject);
    }

    /**
     *  后续处理
     * <p>说明:</p>
     * <li>写缓存</li>
     * <li>持久化</li>
     * <li>刷新客户端</li>
     * @Author DuanYong
     * @Since 2019/8/30 23:17
     * @Version 1.0
     * @Params jsonObject
     */
    private void afterHandle(final JSONObject jsonObject){
        String tradeNo = jsonObject.getString(RESULT_TRADE_NO_KEY);
        String cacheData = cacheService.getCache(Constant.DATA_KEY)+","+tradeNo;
        cacheService.putCache(Constant.DATA_KEY,cacheData);
        persistService.insert(createJSONObject(tradeNo));
        refreshClient(jsonObject);
    }

    /**
     * 推送订单
     * <p>说明:</p>
     * <li></li>
     * @Author DuanYong
     * @Since 2019/8/30 21:36
     * @Version 1.0
     * @Params jsonObject
     * @Return JSONObject
     */
    private JSONObject pushPayOrder(final JSONObject jsonObject) {
        JSONObject paramMap = new JSONObject();
        paramMap.put("payOrderId", jsonObject.getString(RESULT_TRADE_NO_KEY));     // 支付订单号
        paramMap.put("mchOrderNo", jsonObject.getString(RESULT_ORDER_NO_KEY));     // 商户订单号
        paramMap.put("mchId", cacheService.getCache("mchId"));                               // 商户ID
        paramMap.put("appId", cacheService.getCache("appId"));                               // 应用ID
        paramMap.put("productId", cacheService.getCache("productId"));                       // 支付产品
        paramMap.put("amount", AmountUtil.convertDollar2Cent(jsonObject.getString(RESULT_TRADE_AMOUNT_KEY)));                             // 支付金额,单位分
        paramMap.put("currency", "cny");                            // 币种, cny-人民币
        paramMap.put("clientIp", IPUtils.getIpAddr());                 // 用户地址
        paramMap.put("device", "CLIENT");                              // 设备
        paramMap.put("subject", "线下扫码支付");                           // 商品标题
        paramMap.put("body", jsonObject.getString(RESULT_ACCOUNT_EMAIL_KEY)+","+jsonObject.getString(RESULT_ACCOUNT_FULL_NAME_KEY)+","+jsonObject.getString(RESULT_TRANS_MEMO_KEY));                                 // 商品内容
        // 生成签名数据
        String reqSign = SignUtil.getSign(paramMap, cacheService.getCache("key"));
        paramMap.put("sign", reqSign);                              // 签名
        log.info("req:{}", paramMap.toJSONString());
        String url = cacheService.getCache("payUrl");
        // 发起Http请求下单
        String result = httpHandler.post(url,paramMap,"");
        log.info("res:{}", result);
        JSONObject retObj = JSON.parseObject(result);
        return retObj;
    }

    /**
     *  刷新界面数据
     * <p>说明:</p>
     * <li></li>
     * @author DuanYong
     * @since 2019/8/30 13:41
     * @param jsonObject
     * @version 1.0
     */
    private void refreshClient(JSONObject jsonObject){
        Object[] rowData = new Object[8];
        rowData[0] = jsonObject.getString(RESULT_TRADE_TILE_KEY);
        rowData[1] = jsonObject.getString(RESULT_TRADE_NO_KEY);
        rowData[2] = jsonObject.getString(RESULT_ORDER_NO_KEY);
        rowData[3] = jsonObject.getString(RESULT_ACCOUNT_FULL_NAME_KEY)+","+jsonObject.getString(RESULT_ACCOUNT_EMAIL_KEY);
        rowData[4] = jsonObject.getString(RESULT_ACCOUNT_TYPE_KEY);
        rowData[5] = jsonObject.getString(RESULT_TRADE_AMOUNT_KEY);
        rowData[6] = jsonObject.getString(RESULT_BALANCE_KEY);
        rowData[7] = jsonObject.getString(RESULT_TRANS_MEMO_KEY);
        MonitorEventBus.getInstance().post(new DataEvent(DataType.LIST_DATA,rowData));
    }
    /**
     * 创建JSONObject
     * <p>说明:</p>
     * <li></li>
     * @author DuanYong
     * @since 2019/8/30 13:43
     * @param data
     * @return JSONObject
     * @version 1.0
     */
    private JSONObject createJSONObject(String data){
        JSONObject jsonObject = new JSONObject();
        jsonObject.put(Constant.PARAM_KEY,Constant.DATA_KEY);
        jsonObject.put(Constant.PARAM_VALUE,data);
        jsonObject.put(Constant.PARAM_COMMENT,"交易编号");
        return jsonObject;
    }

    /**
     * 获取需要监控的链接
     * <p>说明:</p>
     * <li></li>
     *
     * @author DuanYong
     * @date 2020/9/5 15:37
     */
    @Override
    public String getMonitorUrl() {
        return MONITOR_URL_KEY;
    }
}
